"use strict";
import Web3 from 'web3'
import stringUtil from './utils/stringUtil.js'
import eccrypto from './utils/eccrypto';
import { ethers } from "ethers";
import CryptoJS from "crypto-js";
import {reqweb3} from './contract/reqweb3'
import {getContract} from './contract/getContract'
/**
 * 如果传入账户，用传入的账户，如果不传入，则新生成一个
 * param:
 * 1、privateKey 私钥
 * 2、
 */
class EthShare{
  constructor(obj) {
    this.account = null;
    this.address = ''
    this.publicKey = ''
    //合约部分
    this.contractUrl = 'http://172.30.5.22:8655'
    this.AssetsAddress = '0x1ecf9bd0db0de06a20826037692f745f6a1e6424'
    this.AssetsAbi = '[{"constant":false,"inputs":[{"name":"file_hash","type":"bytes"},{"name":"session_pk","type":"bytes"},{"name":"pwd","type":"bytes"}],"name":"addVaultItem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"page","type":"uint256"},{"name":"page_size","type":"uint256"}],"name":"getVault","outputs":[{"name":"items","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"assetsStorage","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"storageAddrList","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"file_hash","type":"bytes"}],"name":"getAssetDetail","outputs":[{"name":"detail","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"org_file_hash","type":"bytes"},{"name":"page","type":"uint256"},{"name":"page_size","type":"uint256"}],"name":"getAssetCreateLog","outputs":[{"name":"log","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"file_hash","type":"bytes"}],"name":"deleteVaultItem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"org_file_hash","type":"bytes"},{"name":"page","type":"uint256"},{"name":"page_size","type":"uint256"}],"name":"getVaultByOrgFileHash","outputs":[{"name":"items","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"file_hash","type":"bytes"},{"name":"session_pk","type":"bytes"},{"name":"pwd","type":"bytes"}],"name":"updateVaultItem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"file_hash","type":"bytes"},{"name":"org_file_hash","type":"bytes"},{"name":"file_name","type":"string"},{"name":"owner","type":"address"},{"name":"title","type":"string"},{"name":"desc","type":"string"},{"name":"pwd","type":"bytes"},{"name":"witness_expire_time","type":"uint256"}],"name":"newAssets","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"file_hash","type":"bytes"}],"name":"getVaultItem","outputs":[{"name":"detail","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"file_hash","type":"bytes"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"owner","type":"address"}],"name":"assetCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"file_hash","type":"bytes"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"owner","type":"address"}],"name":"assetDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"file_hash","type":"bytes"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"owner","type":"address"}],"name":"itemAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"file_hash","type":"bytes"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"owner","type":"address"}],"name":"itemUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"file_hash","type":"bytes"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"owner","type":"address"}],"name":"itemDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]'

    this.TradeAddress = '0x70e33a90f0c6645ffb51b7c863772a0bc456559d'
    this.TradeAbi = '[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"storageAddrList","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"id","type":"string"}],"name":"getTradeDetail","outputs":[{"name":"detail","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"string"},{"name":"pwd","type":"bytes"}],"name":"setPwd","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"user","type":"address"},{"name":"status","type":"uint8"},{"name":"page","type":"uint256"},{"name":"page_size","type":"uint256"}],"name":"getReceiveTasks","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"string"},{"name":"session_pk","type":"bytes"}],"name":"confirmReceive","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"user","type":"address"},{"name":"status","type":"uint8"},{"name":"page","type":"uint256"},{"name":"page_size","type":"uint256"}],"name":"getSendTasks","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"file_hash","type":"bytes"},{"name":"file_name","type":"string"},{"name":"to","type":"address"},{"name":"title","type":"string"},{"name":"desc","type":"string"}],"name":"newTradeTo","outputs":[{"name":"id","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tradeStorage","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"string"}],"name":"removeTrade","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"string"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"seller","type":"address"}],"name":"tradeCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"string"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"buyer","type":"address"}],"name":"tradeComfirm","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"string"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"seller","type":"address"}],"name":"tradeComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"string"},{"indexed":false,"name":"block_number","type":"uint256"},{"indexed":false,"name":"block_time","type":"uint256"},{"indexed":false,"name":"operator","type":"address"}],"name":"tradeDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]'

    this.WitnessAddress = '0x90f3306e3032bcc905bf210902b66f99b584aa3f'
    this.WitnessAbi = '[{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"services","type":"string"}],"name":"setServices","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"remove","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"storageAddrList","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"website","type":"string"}],"name":"setWebsite","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"email","type":"string"}],"name":"setEmail","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"getDetail","outputs":[{"name":"detail","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"page","type":"uint256"},{"name":"page_size","type":"uint256"}],"name":"getWitnessList","outputs":[{"name":"list","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"getServices","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"name","type":"string"},{"name":"website","type":"string"},{"name":"email","type":"string"},{"name":"services","type":"string"}],"name":"add","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"witnessStorage","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]'
    this.getContractIng = false //是否正在获取合约中


    Object.defineProperty(this, "privateKey", {
      value: this.Init(obj.privateKey?obj.privateKey:''),
      writable: false
    });
    //获取公钥
    const publicKey = this.getPublickey(this.privateKey)
    this.publicKey = publicKey
    console.log('构造函数里公钥',publicKey)


    //获取合约的初始参数.判断，这三个参数必须同时存在
    // if(obj.contracNodeturl && obj.contractNodeAddress && obj.contractNodeAbi){
    //   this.InitContract(obj.contracNodeturl,obj.contractNodeAddress,obj.contractNodeAbi)
    // }else{
    //   this.InitContract()
    // }
    // 初始化对象实例变量
  }
  /**
   * 合约和接口请求相关方法
   * 1、方法名：runweb 方法参数：{requsetArr：[方法名，...方法参数],contractUrl:'合约请求地址'，contractAddress:'合约地址’,
   *  contractAbi:'合约abi'，optional：可选参数，例如回执调用时间间隔}
   * 2、方法名：runwebReq 方法参数：({requestArr:[方法名，...方法参数]}) 默认检索已存在的abi，仅需要传递方法和方法参数，通过检索方法名在某个合约内容中确定使用哪个合约
   */
  runweb(obj){
    //请求合约方法，需要的内容 1、合约地址 2、合约abi  3、账户，由对象对不提供 4、方法参数[]   过滤参数，包括空格，script，特殊字符
    //可选参数 1、reqReceiptTime 回执请求时间间隔
    let requestArr = obj.requestArr
    let account = {
      address:this.address,
      privateKey:this.privateKey
    }
    let requestString = requestArr.join(' ')
    let param3 = {
      req:obj.contractUrl,
      addr:obj.contractAddress,
      abi:obj.contractAbi
    }
    //可选参数，对回执时间做格式校验
    let optional = {
      reqReceiptTime : (obj.reqReceiptTime && stringUtil.isPureNumber)?obj.reqReceiptTime:'',
    }
    console.log('请求参数是',requestString)
    return reqweb3(requestString,account,param3,optional).then(ret=>{
      // console.log('异步返回的',ret)
      return new Promise((resolve,reject)=>{
        resolve(ret)
      })
    })
  }
  //提供一个不需要传入合约和地址的，仅能用我们现有地址 参数名：requsetArr：请求的方法和参数的数组
  async runwebReq(requestArr){
    let reqName = requestArr[0]   //请求的方法名
    //用该方法名去三个合约中寻找 [必须在获取合约结束之后.如何保证]
    if(this.getContractIng){      //如果正在获取合约中，则循环等待
      console.log('等待合约获取中。。。')
      await this.sleep(500)
      return new Promise((resolve,reject)=>{
        let obj = {
          requestArr : requestArr
        }
        resolve(this.runwebReq(obj))
      })
    }else if(this.AssetsAbi && this.TradeAbi && this.WitnessAbi){    //已经获取完合约
      console.log('合约获取完成')
      let objParam = {
        requestArr : requestArr,
        contractUrl : this.contractUrl,
      }
      if(this.AssetsAbi.indexOf(reqName)>-1){
        objParam.contractAddress = this.AssetsAddress
        objParam.contractAbi = this.AssetsAbi
        return new Promise((resolve,reject)=>{
          resolve(this.runweb(objParam))
        })
      }
      if(this.TradeAbi.indexOf(reqName)>-1){
        objParam.contractAddress = this.TradeAddress
        objParam.contractAbi = this.TradeAbi
        return new Promise((resolve,reject)=>{
          resolve(this.runweb(objParam))
        })
      }
      if(this.WitnessAbi.indexOf(reqName)>-1){
        objParam.contractAddress = this.WitnessAddress
        objParam.contractAbi = this.WitnessAbi
        return new Promise((resolve,reject)=>{
          resolve(this.runweb(objParam))
        })
      }

    }else{
      //合约获取不成功，方法取消
      return new Promise((resolve,reject)=>{
        reject('合约内容未获取成功')
      })
    }
  }
  //初始化合约.param:节点地址
  async InitContract(contracNodeturl,contractNodeAddress,contractNodeAbi){
    //通过请求地址和节点，来获取三个合约
    this.getContractIng = true    //正在获取合约中
    if(contracNodeturl && contractNodeAddress && contractNodeAbi){    //如果传入了初始获取合约的地址，则用该地址获取合约
      getContract(contracNodeturl,contractNodeAddress,contractNodeAbi,account).then((arr)=>{
        if(arr.length>0){
          this.setInitContract(arr)
        }
        this.getContractIng = false
      })
    }else{    //如果没有传入获取地址，用默认地址
      let url = 'http://172.30.5.22:8655'
      let addr = '0x0000000000000000000000000000000000001004'
      let abi = '[{"constant":true,"inputs":[{"name":"name","type":"string"}],"name":"selectByName","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"name","type":"string"},{"name":"version","type":"string"}],"name":"selectByNameAndVersion","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]'
      getContract(url,addr,abi,this.account).then((arr)=>{
        if(arr.length>0){
          this.setInitContract(arr)
        }
        this.getContractIng = false
      })
    }
  }
  //设置当前业务合约
  setInitContract(arr){
    this.TradeAddress = arr[0].address
    this.TradeAbi = arr[0].abi
    this.WitnessAddress = arr[1].address
    this.WitnessAbi = arr[1].abi
    this.AssetsAddress = arr[2].address
    this.AssetsAbi = arr[2].abi
    console.log('assets',arr[2])
  }

  /**
   *
   * 账户相关方法
   */
  //初始化账户
  Init(prikey){
    let newA = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
    let account
    if(prikey){     //如果传入了私钥 【检测私钥格式】
        account = newA.eth.accounts.privateKeyToAccount('0x' + prikey);
    }else{
        account = newA.eth.accounts.create()			//创建账户，Object结构
    }
    let pri = account.privateKey.slice(2)   //私钥
    const address = account.address;
    this.account = account
    this.address = address
    console.log('构造函数里地址',address)
    return pri
  }
  //用私钥获取自己的公钥
  getPublickey(privatekey){
    let _privateKey
    if(!privatekey){
      let myprivateKey = this.privateKey
      _privateKey = myprivateKey
    }else{
      _privateKey = privatekey
    }
    let buff = stringUtil.fromHexString(_privateKey);   //转换私钥
    let pubA = eccrypto.getPublicNew(buff);		 //临时生成的公钥
    let publicKey = stringUtil.uint8Array(pubA);
    return '0x'+publicKey
  }
  //用密码加密私钥,参数：1、自定义密码，不为空
  encryptKey(password){
    if(password==='' || password===null){
      return new Promise((resolve,reject)=>{
        reject('密码格式不正确')
      })
    }
    password = password.toString()
    let wallet = new ethers.Wallet(this.privateKey)
    return wallet.encrypt(password, {scrypt: {N: 16384}}).then((keystore)=>{   //keystore 为一段字符串
      return new Promise((resolve,reject)=>{
        console.log('原始代码keystore',typeof keystore)
        resolve(keystore)
      })
    })
  }
  //解锁私钥，参数：1、加密的私钥 2、密码
  decryptKey(encryptPrivateKey,password){
    let encry = encryptPrivateKey.toString()
    return ethers.Wallet.fromEncryptedJson(encry,password).then((wallet2)=>{
      let obj = {}
      obj.address = wallet2.address
      if(wallet2.privateKey.substr(0,2)=='0x'){
        obj.privateKey = wallet2.privateKey.slice(2)
      }else{
        obj.privateKey = wallet2.privateKey
      }
      return new Promise((resolve, reject) => {
        resolve(obj)
      })
    }).catch(error=>{
      return new Promise((resolve,reject)=>{
        reject('解密失败',error)
      })
    })
  }
  //setPrivateKey  切换该对象的私钥的方法，预留接口，暂不提供
  setPrivateKey(newPrivateKey){
  }
  //公钥加密（注意区分与加密私钥不同）(加参数，可以用别人的公钥加密)
  encryptPassword(publicKey,password){
    // let privateKey = Buffer.from(this.privateKey, 'hex');   //该私钥是已经去掉0x开头的
    let pubK = publicKey
    // let pubK = publicKey ? publicKey : eccrypto.getPublic(privateKey);
    let encrypted = eccrypto.encrypt(Buffer.from(pubK, 'hex')  , Buffer.from(password));
    let pwdhex = '0x' + stringUtil.buf2hex(encrypted)
    return pwdhex
  }
  //私钥解密(传私钥，)
  decryptPassword(pwdstr){
    let priKey = this.privateKey
    let privateKey = Buffer.from(priKey, 'hex');
    if(pwdstr.slice(0,2)=='0x'){
      pwdstr = pwdstr.slice(2)
    }
    let decrypt = eccrypto.decrypt(stringUtil.fromHexString(privateKey), stringUtil.fromHexString(pwdstr));
    return decrypt.toString()
  }


  /**
   *
   *
   * 文件加解密相关方法 （文件的加密解密都是用明文密码，另外会提供用公钥加密密码和用私钥解密密码的方法）
   */
  //获取文件hash
  async getFileHash(raw){
    return new Promise((resolve,reject)=>{
      var reader = new FileReader();
      reader.readAsArrayBuffer(raw);
      reader.onload=function(e){    //读文件
        var readAsArrayBuffer=reader.result;    //读取的文件内容
        //test
        // that.org_hash = that.getorgHash(readAsArrayBuffer)
        var FileSHA256 = CryptoJS.algo.SHA256.create(); //新建一个对象
        FileSHA256.update(stringUtil.arrayBufferToWordArray(readAsArrayBuffer)); //根据其项目中的描述，可以通过这种方法将数据分段后加载，但是因为crypto-js这个库不能直接接受arraybuffer，所以要进行转换。
        var FileHash = FileSHA256.finalize(); //获取最终的文件hash，注意这个finalize只能调用一次，多次调用会出错。
        let str = FileHash.toString()
        // return '0x'+str
        resolve('0x'+str)
      }
    })
  }
  //【加密】【小文件】传入文件流和明文文件密码
  encryptFile(raw,filePWD){
    let that = this
    //需要知道，文件后缀名，文件名
    let reader = new FileReader();
    reader.readAsArrayBuffer(raw);
    reader.onload = (e)=>{
      let readAsArrayBuffer=reader.result;    //读取的文件内容
      console.log('查看文件内容',readAsArrayBuffer)
      //1.将读取的arraybuffer转为16进制
      //   let filePWD = stringUtil.randomWord();     //随机生成文件加密密码
      // let filePWD = 'JRN4vlBjBQg8UbF7'
      console.log('密码是',filePWD)
      let word_buffer = stringUtil.arrayBufferToWordArray(readAsArrayBuffer)        //原代码
      var encryptedData = CryptoJS.AES.encrypt(word_buffer, CryptoJS.enc.Utf8.parse(filePWD), {    //加密文件 原代码
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
      })
      let grandstr = ''
      grandstr = encryptedData.ciphertext.toString()
      let typedArray =  new Uint8Array(stringUtil.fromHexString(grandstr))      //最后一轮耗时任务
      let bbuffer = typedArray.buffer			//已将字符串转回buffer
      let blob = new Blob([bbuffer]);
      that.saveBlobAs(blob,filePWD+'.vault')       //自动下载加密文件
    }
  }
  //【加密,返回流】【小文件】传入文件流和明文文件密码
  async encryptFileBuffer(raw,filePWD){
    return new Promise((resolve,reject)=>{
      let that = this
      //需要知道，文件后缀名，文件名
      let reader = new FileReader();
      reader.readAsArrayBuffer(raw);
      reader.onload = async (e)=>{
        let readAsArrayBuffer=reader.result;    //读取的文件内容
        console.log('查看文件内容',readAsArrayBuffer)
        //1.将读取的arraybuffer转为16进制
        //   let filePWD = stringUtil.randomWord();     //随机生成文件加密密码
        // let filePWD = 'JRN4vlBjBQg8UbF7'
        console.log('密码是',filePWD)
        let word_buffer = stringUtil.arrayBufferToWordArray(readAsArrayBuffer)        //原代码
        var encryptedData = CryptoJS.AES.encrypt(word_buffer, CryptoJS.enc.Utf8.parse(filePWD), {    //加密文件 原代码
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7
        })
        let grandstr = ''
        grandstr = encryptedData.ciphertext.toString()
        let typedArray =  new Uint8Array(stringUtil.fromHexString(grandstr))      //最后一轮耗时任务
        let bbuffer = typedArray.buffer			//已将字符串转回buffer
        let blob = new Blob([bbuffer],{ type: 'blob' });
        console.log('ethshare得到的blobs是',blob)
        resolve(blob)
      }
    })
  }


  //【解密】【小文件】传入加密的文件、明文文件密码、解密后的文件名(包括后缀名)
  decodeFile(readAsArrayBuffer,filepwd,filename){

    let that = this

    let buf = stringUtil.buf2hex(readAsArrayBuffer)		//转16进制，流转16进制
    console.log('buf:',buf);
    let encryptedHexStr  = CryptoJS.enc.Hex.parse(buf);   //16进制转wordArray
    console.log('wordArray:',encryptedHexStr);

    let encryptedBase64Str  = CryptoJS.enc.Base64.stringify(encryptedHexStr);    //wordArray转base64

    console.log('encryptedBase64Str:',encryptedBase64Str);
    let decryptedData  = CryptoJS.AES.decrypt(encryptedBase64Str, CryptoJS.enc.Utf8.parse(filepwd), {   //原代码
      iv:[],
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7
    })

    let grandstr = decryptedData.toString()

    console.log('解密--',decryptedData)
    console.log('解密  grandstr--',grandstr)
    let buffer = stringUtil.fromHexString(grandstr)

    let base64 = buffer.toString('base64')
    console.log('buffer base64:',base64);
    let typedArray = Array.from( new Uint8Array(buffer) )
    console.log('typedArray',typedArray);
    return typedArray


    // //已将字符串转回buffer
    // let typedArray = new Uint8Array(stringUtil.fromHexString(grandstr))
    // console.log('typedArray',typedArray);
    // let bbuffer = typedArray.buffer
    // console.log('buffer',bbuffer);
    // let blob = new Blob(typedArray);
    // // that.saveBlobAs(blob,filename)
    // console.log('blob:',blob);
    //
    // return URL.createObjectURL(blob)


    let raw = decodefileStreamRaw
    let reader = new FileReader();
      console.log('decode file:',reader);
    reader.readAsArrayBuffer(raw);
    reader.onload = (e)=>{
      //1.将读取的arraybuffer转为16进制   //原代码,需要
      let readAsArrayBuffer=reader.result;
      let buf = stringUtil.buf2hex(readAsArrayBuffer)		//转16进制，流转16进制
      let encryptedHexStr  = CryptoJS.enc.Hex.parse(buf);   //16进制转wordArray
      let encryptedBase64Str  = CryptoJS.enc.Base64.stringify(encryptedHexStr);    //wordArray转base64

      let decryptedData  = CryptoJS.AES.decrypt(encryptedBase64Str, CryptoJS.enc.Utf8.parse(filepwd), {   //原代码
        iv:[],
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
      })
      let grandstr = ''
      grandstr = decryptedData.toString()
      console.log('解密',decryptedData)
      let typedArray = new Uint8Array(stringUtil.fromHexString(grandstr))
      let bbuffer = typedArray.buffer			//已将字符串转回buffer

      let blob = new Blob([bbuffer]);
      that.saveBlobAs(blob,filename)
    }
  }

  //【解密,返回流】【小文件】传入加密的文件、明文文件密码、解密后的文件名(包括后缀名)
  async decodeFileBuffer(decodefileStreamRaw,filepwd,filename){
    return new Promise((resolve,reject)=>{
      let that = this
      let raw = decodefileStreamRaw
      let reader = new FileReader();
      reader.readAsArrayBuffer(raw);
      reader.onload = (e)=>{
        //1.将读取的arraybuffer转为16进制   //原代码,需要
        let readAsArrayBuffer=reader.result;
        let buf = stringUtil.buf2hex(readAsArrayBuffer)		//转16进制，流转16进制
        let encryptedHexStr  = CryptoJS.enc.Hex.parse(buf);   //16进制转wordArray
        let encryptedBase64Str  = CryptoJS.enc.Base64.stringify(encryptedHexStr);    //wordArray转base64
        let decryptedData  = CryptoJS.AES.decrypt(encryptedBase64Str, CryptoJS.enc.Utf8.parse(filepwd), {   //原代码
          iv:[],
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7
        })
        let grandstr = ''
        grandstr = decryptedData.toString()
        console.log('解密',decryptedData)
        let typedArray = new Uint8Array(stringUtil.fromHexString(grandstr))
        let bbuffer = typedArray.buffer			//已将字符串转回buffer

        let blob = new Blob([bbuffer]);
        console.log('sdk解密文件blob',blob)
        resolve(blob)
      }
    })
  }

  //【加密】【大文件】
  async encryptFileByStream(raw,callback){
    let that = this
    let reader = new FileReader();
    reader.readAsArrayBuffer(raw);
    reader.onload = async (e)=>{
      let readAsArrayBuffer=reader.result;    //读取的文件内容
      //   let filePWD = stringUtil.randomWord();     //随机生成文件加密密码
      let filePWD = 'JRN4vlBjBQg8UbF7'
      console.log('密码是',filePWD)
      let word_buffer = stringUtil.arrayBufferToWordArray(readAsArrayBuffer)        //原代码
      var encryptedData = CryptoJS.AES.encrypt(word_buffer, CryptoJS.enc.Utf8.parse(filePWD), {    //加密文件 原代码
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7
      })
      let block = 1024*1024     //每次分割的大小，这里并不是实际内存的大小
      let arr_circ = encryptedData.ciphertext.words;    //加密完成后文件
      let blockNum = Math.ceil((arr_circ.length)/block)       //根据文件大小分段读取
      let grandstr = ''
      for(let progress = 0; progress < blockNum + 1; progress++){
        let mid = {}        //中间变量
        mid.words = arr_circ.slice(progress*block,(progress+1)*block)
        Object.setPrototypeOf(mid,encryptedData.ciphertext.__proto__)
        mid.sigBytes = (mid.words.length)*4
        grandstr = grandstr+ mid.toString(CryptoJS.enc.Hex)
        if (callback && typeof callback === 'function') {   //回调函数，用户在分段加密中可执行一些更新界面的操作
          callback()
        }
        await new Promise(resolve => setTimeout(resolve, 0));
        if(progress >= blockNum){     //获取完成了
        }
      }
      let typedArray =  new Uint8Array(stringUtil.fromHexString(grandstr))
      let bbuffer = typedArray.buffer			//已将字符串转回buffer
      let blob = new Blob([bbuffer]);
      that.saveBlobAs(blob,filePWD+'.vault')       //自动下载加密文件
    }
  }

  //【解密】【大文件】
  async decodeFileByStream(raw,filepwd,filename,callback){
    let that = this
    let reader = new FileReader();
    reader.readAsArrayBuffer(raw);
    reader.onload = async (e)=>{
      //1.将读取的arraybuffer转为16进制   //原代码,需要
      let readAsArrayBuffer=reader.result;
      console.log('解密1')
      // let buf = stringUtil.buf2hex(readAsArrayBuffer)		//转16进制，流转16进制
      let buf = stringUtil.arrayBufferToHex(readAsArrayBuffer)
      console.log('解密2')
      let encryptedHexStr  = CryptoJS.enc.Hex.parse(buf);   //16进制转wordArray
      console.log('解密3')
      let encryptedBase64Str  = CryptoJS.enc.Base64.stringify(encryptedHexStr);    //wordArray转base64
      console.log('开始解密')
      let decryptedData  = CryptoJS.AES.decrypt(encryptedBase64Str, CryptoJS.enc.Utf8.parse(filepwd), {   //原代码
        iv:[],
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
      })
      console.log('解密完成，开始组装',decryptedData)
      let block = 1024*1024     //每次分割的大小，这里并不是实际内存的大小
      let arr_circ = decryptedData.words;    //加密完成后文件
      let blockNum = (arr_circ.length)/block       //根据文件大小分段读取
      let grandstr = ''
      for(let progress = 0; progress < blockNum + 1; progress++){
        console.log('解密过程中',progress)
        let mid = {}        //中间变量
        mid.words = arr_circ.slice(progress*block,(progress+1)*block)
        Object.setPrototypeOf(mid,decryptedData.__proto__)
        mid.sigBytes = (mid.words.length)*4
        grandstr = grandstr+ mid.toString(CryptoJS.enc.Hex)
        if (callback && typeof callback === 'function') {   //回调函数，用户在分段加密中可执行一些更新界面的操作
          callback()
        }
        await new Promise(resolve => setTimeout(resolve, 0));
        if(progress >= blockNum){     //获取完成了
        }
      }
      console.log('解密完了')
      let typedArray = new Uint8Array(stringUtil.fromHexString(grandstr))
      let bbuffer = typedArray.buffer			//已将字符串转回buffer

      let blob = new Blob([bbuffer]);

      that.saveBlobAs(blob,filename)
    }
  }

  //分别提供一个加解密文件的输出流版本，供方便使用node下载【或者以此为基础，修改之前的后续操作为传入回调函数】

  //通过传入文件获取文件hash的函数

  //通过公钥加密明文字符串密码的函数。规定密码的位数和格式

  //通过私钥解密加密字符串密码的函数。规定密码的位数和格式，否则无法解密

  //在浏览器下载文件流为本地文件，参数 1、blob 2、要保存的文件名，包括后缀名
  saveBlobAs(blob, filename) {
    if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE
      window.navigator.msSaveOrOpenBlob(blob, filename);
    } else { // Chrome/Firefox/Safari/Edge
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = filename;
      a.click();
      setTimeout(() => window.URL.revokeObjectURL(url), 1000); // 释放对象 URL
    }
  }

  //通过文件获取hash的函数


  /**
   *
   * 快捷业务方法，封装现有业务请求方法
  */
  /**【Asset合约】*/
  //获取资产列表
  getVaultList(page,pageSize){
    this.runwebReq(['getVault',page,pageSize]).then(res=>{
      console.log('得到结果',res)
    })
  }
  //根据资产hash获取资产详情
  async getVaultDetail(hash){
    return new Promise((resolve,reject)=>{
      this.runwebReq(['getAssetDetail',hash]).then(res=>{
        resolve(res)
      })
    })
  }
  //新增资产
  newAssets(obj){
    //1、文件hash 2、原始hash 3、资产拥有者 4、资产标题 5、资产描述 6、资产密码（用自己公钥加密的密码） 7、鉴证过期时间，时间戳
    console.log('这是什么',['newAssets',obj.file_hash, obj.org_file_hash, obj.owner, obj.title, obj.desc, obj.pwd, obj.witness_expire_time])
    this.runwebReq(['newAssets',obj.file_hash, obj.org_file_hash, obj.file_name, obj.owner, obj.title, obj.desc, obj.pwd, obj.witness_expire_time]).then(res=>{
      console.log('新增资产详情',res)
    })
  }
  //获取自己的保险库详情,传入文件hash
  async getVaultItem(hash){
    return new Promise((resolve,reject)=>{
      this.runwebReq(['getVaultItem',hash]).then(res=>{
        resolve(res)
      })
    })
  }
  //根据源文件hash查询
  getAssetCreateLog(org_hash,page,pageSize){
    this.runwebReq(['getAssetCreateLog',org_hash, page, pageSize]).then(res=>{
      console.log('根据原文件hash查询',res)
    })
  }

  /**【交易trade合约】*/
  //指定接收方
  newTradeTo(obj){
    this.runwebReq(['newTradeTo',obj.file_hash, obj.file_name, obj.to, obj.title, obj.desc]).then(res=>{
      console.log('指定接收方交易成功',res)
    })
  }
  //交易详情,参数交易id
  getTradeDetail(id){
    this.runwebReq(['getTradeDetail',id]).then(res=>{
      console.log('获取交易详情成功',res)
    })
  }
  //买方确认接收到文件
  confirmReceive(id){
    let session_pk = this.publicKey
    this.runwebReq(['confirmReceive',id, session_pk]).then(res=>{
      console.log('确认接收文件成功',res)
    })
  }
  //获取该交易的用来加密的公钥,参数：交易id
  getSessionPk(id){
    this.runwebReq(['getSessionPk',id]).then(res=>{
      console.log('获取该交易的用来加密的公钥成功',res)
    })
  }
  //卖方发送密码（将用买家公钥加密后的文件密码上链）
  setPwd(id,password){
    this.runwebReq(['setPwd',id, password]).then(res=>{
      console.log('卖方发送密码成功',res)
    })
  }
  // 卖方删除任务 // removeTrade(uint256 id)
  removeTrade(id){
    this.runwebReq(['removeTrade',id]).then(res=>{
      console.log('卖方删除任务成功',res)
    })
  }
  // 获取指定用户的发送任务id列表
  getSendTasks(obj){
    this.runwebReq(['getSendTasks',obj.user, obj.status, obj.page, obj.page_size]).then(res=>{
      console.log('获取指定用户的发送任务id列表成功',res)
    })
  }
  /**【鉴证witness合约】 */
  //获取鉴证方地址
  getWitnessList(page,page_size){
    this.runwebReq(['getWitnessList', page, page_size]).then(res=>{
      console.log('获取鉴证方地址成功',res)
    })
  }
  //添加鉴证方
  //该方法add,可能用indexOF查询不到是哪个合约
  addWitness(obj){
    this.runwebReq(['add', obj.account, obj.name, obj.website, obj.email, obj.services]).then(res=>{
      console.log('添加鉴证方成功',res)
    })
  }
  //删除鉴证方
  removeWitness(account){
    this.runwebReq(['remove', account]).then(res=>{
      console.log('删除鉴证方成功',res)
    })
  }
  //鉴证方详情
  getWitnessDetail(account){
    this.runwebReq(['getDetail', account]).then(res=>{
    })
  }
  // 设定service // setServices(address account, string memory services)
  //鉴证方详情
  getWitnessDetail(account,services){
    this.runwebReq(['getWitnessDetail', account, services]).then(res=>{
    })
  }
  //查询service // getServices(address account)
  getServices(account){
    this.runwebReq(['getServices', account]).then(res=>{
    })
  }





  async sleep(duration){
    return new Promise(function(resolve){
      setTimeout(resolve, duration);
    })
  }
}
// module.exports.EthShare = EthShare
export default EthShare
